package com.xyz.study.design_mode.e_singleton.mode;

/**
 * 双重检查懒汉式单例模式
 * @author XYZ
 * @version 1.0.0
 * @since 2021/1/18
 */
public class DoubleCheckLazySingleton {

    /**
     * 不使用volatile声明的话可能因为创建对象的三个流程（1分配空间2初始化对象3引用指向内存地址）的重排序（2和3重排序）导致对象还没有初始化完成就使用
     * 由于happens-before，对于volatile变量doubleCheckLazySingleton，所有的写（write）都将先行发生于读（read）,所以能够禁止创建对象的重排序
     */
    private static volatile DoubleCheckLazySingleton doubleCheckLazySingleton;

    private DoubleCheckLazySingleton(){
    }

    //DCL对instance进行了两次null判断
    //第一层判断主要是为了避免不必要的同步
    //第二层的判断则是为了在null的情况下创建实例。第一层判断假如有好几个线程同时通过了判断，这是线程1进入临界区执行代码，创建了对象，这时释放了锁，如果没有第二层判断，其他通过第一层判断的线程再进入临界区又会再创建对象。
    public static DoubleCheckLazySingleton instance(){
        if(null == doubleCheckLazySingleton){
            synchronized (DoubleCheckLazySingleton.class){
                if (null == doubleCheckLazySingleton){
                    doubleCheckLazySingleton = new DoubleCheckLazySingleton();
                }
            }
        }
        return doubleCheckLazySingleton;
    }

    public void doSomething(){
        System.out.println("使用双重检查懒汉式单例模式。");
    }
}
